// Copyright (c) 2011 Xi Minggao <brooks.xi@gmail.com>. All rights reserved.
// Use of this source code is governed by the New BSD License that can be
// found in the LICENSE file.

#include "comm/Protocol.hxx"
#include "comm/Exception.hxx"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <boost/lexical_cast.hpp>

using namespace kiwii::comm;
using namespace kiwii::comm::protocol;

TEST(Protocol, RequestOK) {
  char buf[] = "*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n";
  Request req(buf, sizeof(buf) - 1);

  ASSERT_TRUE(req.ok());
  EXPECT_EQ((std::size_t)3, req.argNum());
  EXPECT_EQ("SET", req.arg(0));
  EXPECT_EQ("mykey", req.arg(1));
  EXPECT_EQ("myvalue", req.arg(2));
  EXPECT_EQ(sizeof(buf) - 1, req.bytes());
}

TEST(Protocol, RequestIncomplete) {
  char buf[] = "*2\r\n$5\r";
  Request req(buf, sizeof(buf) - 1);

  ASSERT_FALSE(req.ok());
  EXPECT_TRUE(req.argNum() == 0);
  EXPECT_TRUE(req.bytes() == 0);
}

TEST(Protocol, RequestInvalid) {
  char buf[] = "*2\r\n$3\r\nSET\r\n?2\r\nON\r\n";
  Request req(buf, sizeof(buf));

  ASSERT_FALSE(req.ok());
  EXPECT_EQ((unsigned)0, req.argNum());
  EXPECT_EQ(sizeof(buf), req.bytes());

  char buf2[] = "#2\r\n$3\r\nSET\r\n$2\r\nON\r\n";
  Request req2(buf2, sizeof(buf2));
  ASSERT_FALSE(req2.ok());
  EXPECT_EQ((unsigned)0, req.argNum());
  EXPECT_EQ(sizeof(buf2), req.bytes());
}

TEST(Protocol, singleLineReply) {
  EXPECT_EQ("+OK\r\n", Reply().status("OK").toString());
  EXPECT_EQ("-something wrong\r\n", Reply().error("something wrong").toString());
  EXPECT_EQ(":1000\r\n", Reply().integer(1000).toString());
}

TEST(Protocol, bulkReply) {
  EXPECT_EQ("$6\r\nfoobar\r\n", Reply().bulk("foobar").toString());
}

TEST(Protocol, multiBulkReply) {
  auto reply = Reply().multiBulk();
  reply << "foo" << "bar";
  EXPECT_EQ("*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n", reply.toString());
}

